/*
 * rosa_queues.c
 *
 * Created: 2014-12-03 13:47:12
 *  Author: eds04001
 */ 

#ifndef NULL
#define NULL 0
#endif

/***********************************************************
 * TCB block
 *
 * Comment:
 * 	This struct contain all the necessary information to
 * 	do a context switch
 *
 **********************************************************/
#include "rosa_queues.h"



tcb *readyQueueHead=NULL;
tcb *waitingQueueHead=NULL;

int ROSA_addToReadyQueue(tcb *newTask)
{ 
	
	if(readyQueueHead==NULL)
	    {
			readyQueueHead =newTask;
		}
	else
	{
		tcb *temp = readyQueueHead;
		if(newTask->priority>readyQueueHead->priority)
		{
			newTask->nexttcb = readyQueueHead;
			readyQueueHead = newTask;
			return 0;
		}

		while(temp->nexttcb != NULL)
		{	
			
			if(newTask->priority>temp->nexttcb->priority)
			{
				newTask->nexttcb = temp->nexttcb;
				temp->nexttcb = newTask;
				return 0;
			}
			
			temp=temp->nexttcb;

		}	
		temp->nexttcb = newTask;
		
		return 0;		
		
	}
	return -1;
}
int ROSA_moveToRunning()
{

	readyQueueHead = readyQueueHead->nexttcb;

	return 0;
}
int ROSA_addToWaitingQueue(tcb *newTask,unsigned int time)
{
	newTask->wakeUpTime = time;
	if(waitingQueueHead==NULL)
	{
		waitingQueueHead = newTask;		
		return 0;
	}
	else
	{	
		tcb *temp = waitingQueueHead;
		if(newTask->wakeUpTime< waitingQueueHead->wakeUpTime)
		{
			newTask->nexttcb = waitingQueueHead;
			waitingQueueHead = newTask;
			return 0;
		}
		
		while( temp->nexttcb !=NULL)
		{
			if(newTask->wakeUpTime<time)
			{
				newTask->nexttcb = temp->nexttcb;
				temp->nexttcb = newTask;				
				return 0;
			}
		
			temp=temp->nexttcb;
		}
		temp->nexttcb = newTask;				
		return 0;
	}
	return -1;
}
int ROSA_removeFromWaitingQueue()
{
	tcb *temp = waitingQueueHead;
	waitingQueueHead = waitingQueueHead->nexttcb;
	temp->nexttcb = NULL;

	ROSA_addToReadyQueue(temp);
	return 0;
}
void ROSA_tcbCreate(tcb * tcbTask, char tcbName[4], void *tcbFunction, int * tcbStack, int tcbStackSize,int priority)
{
	int i;

	//Initialize the tcb with the correct values
	for(i = 0; i < 4; i++) {
		//Copy the id/name
		tcbTask->id[i] = tcbName[i];
	}

	//Dont link this TCB anywhere yet.
	tcbTask->nexttcb = NULL;

	//Set the task function start and return address.
	tcbTask->staddr = tcbFunction;
	tcbTask->retaddr = (int)tcbFunction;

	//Set up the stack.
	tcbTask->datasize = tcbStackSize;
	tcbTask->dataarea = tcbStack + tcbStackSize;
	tcbTask->saveusp = tcbTask->dataarea;
	tcbTask->priority =priority;

}

